package com.blog.cmrpersonalblog.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.blog.cmrpersonalblog.dto.auth.request.LoginRequest;
import com.blog.cmrpersonalblog.dto.auth.request.RegisterRequest;
import com.blog.cmrpersonalblog.dto.auth.request.VerifyEmailCodeRequest;
import com.blog.cmrpersonalblog.dto.auth.response.LoginResponse;
import com.blog.cmrpersonalblog.entity.SysRole;
import com.blog.cmrpersonalblog.entity.SysUser;
import com.blog.cmrpersonalblog.service.AuthService;
import com.blog.cmrpersonalblog.service.EmailVerificationService;
import com.blog.cmrpersonalblog.service.SysRoleService;
import com.blog.cmrpersonalblog.service.SysUserRoleService;
import com.blog.cmrpersonalblog.service.SysUserService;
import com.blog.cmrpersonalblog.service.UserActivityService;
import com.blog.cmrpersonalblog.utils.PasswordUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 认证服务实现类
 */
@Slf4j
@Service
public class AuthServiceImpl implements AuthService {

   @Resource
    private SysUserService sysUserService;

   @Resource
    private SysRoleService sysRoleService;

   @Resource
    private SysUserRoleService sysUserRoleService;

   @Resource
    private EmailVerificationService emailVerificationService;

   @Resource
    private HttpServletRequest request;

   @Resource
    private UserActivityService userActivityService;

    @Override
    public LoginResponse login(LoginRequest loginRequest) {
        String clientIp = getClientIp();
        String userAgent = request.getHeader("User-Agent");

        // 1. 验证用户名和密码
        SysUser user = sysUserService.getUserByUserName(loginRequest.getUserName());
        if (user == null) {
            // 记录登录失败（用户不存在）
            userActivityService.recordLoginActivity(null, false, clientIp, userAgent, "用户不存在");
            throw new RuntimeException("用户名或密码错误");
        }

        if (user.getStatus() != 1) {
            // 记录登录失败（用户被禁用）
            userActivityService.recordLoginActivity(user.getUserId(), false, clientIp, userAgent, "用户已被禁用");
            throw new RuntimeException("用户已被禁用");
        }

        if (!sysUserService.verifyPassword(user, loginRequest.getPassword())) {
            // 记录登录失败（密码错误）
            userActivityService.recordLoginActivity(user.getUserId(), false, clientIp, userAgent, "密码错误");
            throw new RuntimeException("用户名或密码错误");
        }

        // 2. 更新用户登录信息
        user.setLoginIp(clientIp);
        user.setLoginDate(LocalDateTime.now());
        sysUserService.updateUserLoginInfo(user);

        // 3. 执行登录操作
        StpUtil.login(user.getUserId());

        // 4. 记录登录成功
        userActivityService.recordLoginActivity(user.getUserId(), true, clientIp, userAgent, null);

        // 5. 获取用户角色和权限
        List<String> roles = sysUserService.getUserRoles(user.getUserId());
        List<String> permissions = sysUserService.getUserPermissions(user.getUserId());

        // 6. 构建响应
        LoginResponse response = new LoginResponse();
        response.setToken(StpUtil.getTokenValue());
        response.setUserId(user.getUserId());
        response.setUserName(user.getUserName());
        response.setNickName(user.getNickName());
        response.setAvatar(user.getAvatar());
        response.setRoles(roles);
        response.setPermissions(permissions);
        response.setExpireTime(StpUtil.getTokenTimeout());

        return response;
    }

    @Override
    public boolean logout() {
        try {
            // 检查是否已登录，如果未登录也认为注销成功
            if (!StpUtil.isLogin()) {
                return true;
            }
            StpUtil.logout();
            return true;
        } catch (Exception e) {
            // 即使注销失败，也返回true，因为目标是让用户退出
            return true;
        }
    }

    @Override
    public LoginResponse refreshToken() {
        // 检查是否已登录
        if (!StpUtil.isLogin()) {
            throw new RuntimeException("用户未登录");
        }

        Long userId = StpUtil.getLoginIdAsLong();
        SysUser user = sysUserService.getById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        // 获取用户角色和权限
        List<String> roles = sysUserService.getUserRoles(userId);
        List<String> permissions = sysUserService.getUserPermissions(userId);

        // 构建响应
        LoginResponse response = new LoginResponse();
        response.setToken(StpUtil.getTokenValue());
        response.setUserId(userId);
        response.setUserName(user.getUserName());
        response.setNickName(user.getNickName());
        response.setAvatar(user.getAvatar());
        response.setRoles(roles);
        response.setPermissions(permissions);
        response.setExpireTime(StpUtil.getTokenTimeout());

        return response;
    }

    @Override
    public LoginResponse getCurrentUser() {
        return refreshToken();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LoginResponse register(RegisterRequest registerRequest) {
        String clientIp = getClientIp();
        String userAgent = request.getHeader("User-Agent");

        try {
            // 1. 验证密码确认
            if (!registerRequest.getPassword().equals(registerRequest.getConfirmPassword())) {
                throw new RuntimeException("两次输入的密码不一致");
            }

            // 2. 检查用户名是否已存在
            SysUser existingUser = sysUserService.getUserByUserName(registerRequest.getUserName());
            if (existingUser != null) {
                throw new RuntimeException("用户名已存在");
            }

            // 3. 检查邮箱是否已存在
            if (sysUserService.isEmailExists(registerRequest.getEmail(), null)) {
                throw new RuntimeException("邮箱已被注册");
            }

            // 3.5. 如果提供了邮箱验证码，则进行验证
            if (registerRequest.getEmailVerificationCode() != null &&
                !registerRequest.getEmailVerificationCode().trim().isEmpty()) {

                VerifyEmailCodeRequest verifyRequest = new VerifyEmailCodeRequest();
                verifyRequest.setEmail(registerRequest.getEmail());
                verifyRequest.setVerificationCode(registerRequest.getEmailVerificationCode());
                verifyRequest.setVerificationType("REGISTER");

                if (!emailVerificationService.verifyAndUseCode(verifyRequest)) {
                    throw new RuntimeException("邮箱验证码无效或已过期");
                }

                log.info("邮箱验证成功: email={}", registerRequest.getEmail());
            }

            // 4. 检查手机号是否已存在（如果提供了手机号）
            if (registerRequest.getPhonenumber() != null && !registerRequest.getPhonenumber().trim().isEmpty()) {
                if (sysUserService.isPhonenumberExists(registerRequest.getPhonenumber(), null)) {
                    throw new RuntimeException("手机号已被注册");
                }
            }

            // 5. 创建用户对象
            SysUser newUser = new SysUser();
            newUser.setUserName(registerRequest.getUserName());
            newUser.setNickName(registerRequest.getNickName());
            newUser.setEmail(registerRequest.getEmail());
            newUser.setPhonenumber(registerRequest.getPhonenumber());
            newUser.setSex(registerRequest.getSex());
            newUser.setStatus(1); // 默认启用状态
            newUser.setCreateBy("system");
            newUser.setCreateTime(LocalDateTime.now());
            newUser.setUpdateTime(LocalDateTime.now());

            // 设置邮箱验证状态
            boolean emailVerified = registerRequest.getEmailVerificationCode() != null &&
                                   !registerRequest.getEmailVerificationCode().trim().isEmpty();
            newUser.setEmailVerified(emailVerified ? 1 : 0);
            if (emailVerified) {
                newUser.setEmailVerifiedTime(LocalDateTime.now());
            }

            // 6. 加密密码
            String encryptedPassword = PasswordUtils.sha256EncryptWithUserSalt(
                registerRequest.getPassword(), registerRequest.getUserName());
            newUser.setPassword(encryptedPassword);

            // 7. 保存用户
            boolean saveResult = sysUserService.save(newUser);
            if (!saveResult) {
                throw new RuntimeException("用户注册失败");
            }

            // 8. 获取user角色并分配给新用户
            SysRole userRole = sysRoleService.getRoleByRoleKey("user");
            if (userRole == null) {
                throw new RuntimeException("系统错误：用户角色不存在");
            }

            // 9. 为用户分配user角色
            boolean assignRoleResult = sysUserRoleService.assignRolesToUser(
                newUser.getUserId(), Arrays.asList(userRole.getId()));
            if (!assignRoleResult) {
                throw new RuntimeException("角色分配失败");
            }

            // 10. 记录注册活动
            Map<String, Object> extraData = new HashMap<>();
            extraData.put("userName", newUser.getUserName());
            extraData.put("email", newUser.getEmail());
            userActivityService.recordActivity(newUser.getUserId(), "USER_REGISTER", "用户注册",
                newUser.getUserId(), "user", "SUCCESS", extraData);

            // 11. 自动登录并返回登录响应
            StpUtil.login(newUser.getUserId());

            // 12. 记录登录活动
            userActivityService.recordLoginActivity(newUser.getUserId(), true, clientIp, userAgent, "注册后自动登录");

            // 13. 获取用户角色和权限
            List<String> roles = sysUserService.getUserRoles(newUser.getUserId());
            List<String> permissions = sysUserService.getUserPermissions(newUser.getUserId());

            // 14. 构建响应
            LoginResponse response = new LoginResponse();
            response.setToken(StpUtil.getTokenValue());
            response.setUserId(newUser.getUserId());
            response.setUserName(newUser.getUserName());
            response.setNickName(newUser.getNickName());
            response.setAvatar(newUser.getAvatar());
            response.setRoles(roles);
            response.setPermissions(permissions);
            response.setExpireTime(StpUtil.getTokenTimeout());

            return response;

        } catch (Exception e) {
            // 记录注册失败活动
            Map<String, Object> failureData = new HashMap<>();
            failureData.put("error", e.getMessage());
            failureData.put("userName", registerRequest.getUserName());
            userActivityService.recordActivity(null, "USER_REGISTER", "用户注册失败",
                null, "user", "FAILED", failureData);
            throw new RuntimeException("注册失败：" + e.getMessage(), e);
        }
    }

    /**
     * 获取客户端IP地址
     */
    private String getClientIp() {
        String xip = request.getHeader("X-Real-IP");
        String xfor = request.getHeader("X-Forwarded-For");
        if (xfor != null && !xfor.isEmpty() && !"unknown".equalsIgnoreCase(xfor)) {
            int index = xfor.indexOf(",");
            if (index != -1) {
                return xfor.substring(0, index);
            } else {
                return xfor;
            }
        }
        if (xip != null && !xip.isEmpty() && !"unknown".equalsIgnoreCase(xip)) {
            return xip;
        }
        if (xfor != null && !xfor.isEmpty() && !"unknown".equalsIgnoreCase(xfor)) {
            return xfor;
        }
        return request.getRemoteAddr();
    }
}
